from pulp import LpMaximize, LpProblem, LpVariable, lpSum, PULP_CBC_CMD
from common_import import *


def solve_DEF(samples_list):
    # 创建问题
    model = LpProblem(name="maximize-profit-water-fields", sense=LpMaximize)

    # region D

    # 地块、作物、时间范围
    landsD = ["D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8"]
    single_season_cropsD = [16]  # 单季作物编号
    first_season_cropsD = list(range(17, 35))  # 第一季作物编号
    second_season_cropsD = [35, 36, 37]  # 第二季作物编号
    years = range(2024, 2031)  # 时间范围：2024到2030
    field_typeD = "水浇地"

    # 面积数据
    area_of_landD = {
        "D1": 15.0,
        "D2": 10.0,
        "D3": 14.0,
        "D4": 6.0,
        "D5": 10.0,
        "D6": 12.0,
        "D7": 22.0,
        "D8": 20.0,
    }

    # 2023年的种植方案
    known_planting_2023D = {
        "D1": (20, 36),
        "D2": (28, 35),
        "D3": (21, 35),
        "D4": (22, 35),
        "D5": (17, 36),
        "D6": (18, 37),
        "D7": (16, None),
        "D8": (16, None),
    }

    # 每种作物的总销量（/斤）
    total_salesD = {
        16: 21000,
        35: 150000,
        36: 100000,
        37: 36000,
    }

    # 决策变量
    x_singleD = LpVariable.dicts(
        "x_singleD",
        ((i, j, t) for i in landsD for j in single_season_cropsD for t in years),
        lowBound=0,
        cat="Continuous",
    )
    x_firstD = LpVariable.dicts(
        "x_firstD",
        ((i, j, t) for i in landsD for j in first_season_cropsD for t in years),
        lowBound=0,
        cat="Continuous",
    )
    x_secondD = LpVariable.dicts(
        "x_secondD",
        ((i, j, t) for i in landsD for j in second_season_cropsD for t in years),
        lowBound=0,
        cat="Continuous",
    )
    zD = LpVariable.dicts(
        "zD",
        (
            (i, j, t)
            for i in landsD
            for j in single_season_cropsD + first_season_cropsD + second_season_cropsD
            for t in years
        ),
        cat="Binary",
    )
    M = 1000

    # 修改约束条件，使 x 变量只能为 0 或者大于等于 1
    for i in landsD:
        for t in years:
            # 对于单季作物
            for j in single_season_cropsD:
                model += (
                    x_singleD[i, j, t] >= zD[i, j, t]
                )  # 如果 zD 为 1, 则 x >= 1；如果 zD 为 0, 则 x >= 0
                model += (
                    x_singleD[i, j, t] <= M * zD[i, j, t]
                )  # 如果 zD 为 0, 则 x = 0；如果 zD 为 1, 则 x <= M

            # 对于第一季作物
            for j in first_season_cropsD:
                model += (
                    x_firstD[i, j, t] >= zD[i, j, t]
                )  # 如果 zD 为 1, 则 x >= 1；如果 zD 为 0, 则 x >= 0
                model += (
                    x_firstD[i, j, t] <= M * zD[i, j, t]
                )  # 如果 zD 为 0, 则 x = 0；如果 zD 为 1, 则 x <= M

            # 对于第二季作物
            for j in second_season_cropsD:
                model += (
                    x_secondD[i, j, t] >= zD[i, j, t]
                )  # 如果 zD 为 1, 则 x >= 1；如果 zD 为 0, 则 x >= 0
                model += x_secondD[i, j, t] <= M * zD[i, j, t]

    # 新增变量：表示每种作物每年超出的部分
    overproduction_singleD = LpVariable.dicts(
        "overproduction_singleD",
        ((j, t) for j in single_season_cropsD for t in years),
        lowBound=0,
        cat="Continuous",
    )

    overproduction_secondD = LpVariable.dicts(
        "overproduction_secondD",
        ((j, t) for j in second_season_cropsD for t in years),
        lowBound=0,
        cat="Continuous",
    )

    # 添加约束条件：单季作物的总产量限制
    for j in single_season_cropsD:
        for t in years:
            total_yield_singleD = lpSum(
                mapping.get_yield_idtype(j, field_typeD, "单季")
                * samples_list[t]["亩产量"]
                * x_singleD[i, j, t]
                for i in landsD
            )
            model += (
                total_yield_singleD
                <= total_salesD[j] * samples_list[t]["其他销量"]
                + overproduction_singleD[j, t]
            )
            model += (
                overproduction_singleD[j, t]
                >= total_yield_singleD - total_salesD[j] * samples_list[t]["其他销量"]
            )

    # 添加约束条件：第二季作物的总产量限制
    for j in second_season_cropsD:
        for t in years:
            total_yield_secondD = lpSum(
                mapping.get_yield_idtype(j, field_typeD, "第二季")
                * samples_list[t]["亩产量"]
                * x_secondD[i, j, t]
                for i in landsD
            )
            model += (
                total_yield_secondD
                <= total_salesD[j] * samples_list[t]["其他销量"]
                + overproduction_secondD[j, t]
            )
            model += (
                overproduction_secondD[j, t]
                >= total_yield_secondD - total_salesD[j] * samples_list[t]["其他销量"]
            )

    # 添加新的二进制变量
    y_singleD = LpVariable.dicts(
        "y_singleD", ((i, t) for i in landsD for t in years), cat="Binary"
    )
    y_seasonalD = LpVariable.dicts(
        "y_seasonalD", ((i, t) for i in landsD for t in years), cat="Binary"
    )

    # 约束条件1：每块地可选种植单季植物，或者同时种植第一季和第二季植物
    for i in landsD:
        for t in years:
            model += y_singleD[i, t] + y_seasonalD[i, t] <= 1
            model += (
                lpSum(x_singleD[i, j, t] for j in single_season_cropsD)
                <= area_of_landD[i] * y_singleD[i, t]
            )
            model += (
                lpSum(x_firstD[i, j, t] for j in first_season_cropsD)
                <= area_of_landD[i] * y_seasonalD[i, t]
            )
            model += (
                lpSum(x_secondD[i, j, t] for j in second_season_cropsD)
                <= area_of_landD[i] * y_seasonalD[i, t]
            )

    # 约束条件2：每块地每连续三年必须种植豆类（豆类作物为第一季的17,18）
    for i in landsD:
        model += (
            lpSum(
                (
                    x_firstD[i, j, 2024]
                    + x_firstD[i, j, 2025]
                    + (
                        area_of_landD[i]
                        if (first_crop := known_planting_2023D[i][0]) in [17, 18, 19]
                        else 0
                    )
                )
                for j in [17, 18, 19]
            )
            >= area_of_landD[i]
        )
        for t in range(2024, 2029):
            model += (
                lpSum(x_firstD[i, j, t + k] for j in [17, 18] for k in range(3))
                >= area_of_landD[i]
            )

    # 约束条件3：不能重茬种植（单季、第一季、第二季均不能重茬）
    M = 1000
    for i in landsD:
        for j in single_season_cropsD:
            for t in range(2024, 2030):
                model += x_singleD[i, j, t] <= M * zD[i, j, t]
                model += zD[i, j, t] + zD[i, j, t + 1] <= 1
        for j in first_season_cropsD:
            for t in range(2024, 2030):
                model += x_firstD[i, j, t] <= M * zD[i, j, t]
                model += zD[i, j, t] + zD[i, j, t + 1] <= 1
        for j in second_season_cropsD:
            for t in range(2024, 2030):
                model += x_secondD[i, j, t] <= M * zD[i, j, t]
                model += zD[i, j, t] + zD[i, j, t + 1] <= 1

    # 2024不能重茬种植，包括单季作物、第一季和第二季作物
    for i, (first_crop, second_crop) in known_planting_2023D.items():
        if first_crop in single_season_cropsD:
            model += zD[i, first_crop, 2024] == 0
        if first_crop in first_season_cropsD:
            model += zD[i, first_crop, 2024] == 0
        if second_crop in second_season_cropsD:
            model += zD[i, second_crop, 2024] == 0

    # 添加新的二进制变量
    z_secondD = LpVariable.dicts(
        "z_secondD",
        ((i, j, t) for i in landsD for j in second_season_cropsD for t in years),
        cat="Binary",
    )

    # 约束条件4：每块地在第二季中只能种植一种作物
    for i in landsD:
        for t in years:
            model += lpSum(z_secondD[i, j, t] for j in second_season_cropsD) <= 1
            for j in second_season_cropsD:
                model += x_secondD[i, j, t] <= area_of_landD[i] * z_secondD[i, j, t]

    # 约束条件5：每年单季、第一季、第二季在每块地的种植总面积都要小于该地的面积
    for i in landsD:
        for t in years:
            model += (
                lpSum(x_singleD[i, j, t] for j in single_season_cropsD)
                <= area_of_landD[i]
            )
            model += (
                lpSum(x_firstD[i, j, t] for j in first_season_cropsD)
                <= area_of_landD[i]
            )
            model += (
                lpSum(x_secondD[i, j, t] for j in second_season_cropsD)
                <= area_of_landD[i]
            )

    # endregion

    # region E
    # 地块、作物、时间范围
    landsE = [
        "E1",
        "E2",
        "E3",
        "E4",
        "E5",
        "E6",
        "E7",
        "E8",
        "E9",
        "E10",
        "E11",
        "E12",
        "E13",
        "E14",
        "E15",
        "E16",
    ]
    first_season_cropsE = list(range(17, 35))
    second_season_cropsE = [38, 39, 40, 41]  # 第二季作物编号
    field_typeE = "普通大棚 "

    # 面积数据
    area_of_landE = {land: 0.6 for land in landsE}

    # 每种作物的总销量（/斤）
    total_salesE = {
        38: 9000,
        39: 7200,
        40: 18000,
        41: 4200,
    }

    # 2023年的种植方案
    known_planting_2023E = {
        "E1": (18, 38),
        "E2": (24, 38),
        "E3": (25, 38),
        "E4": (26, 39),
        "E5": (28, 39),
        "E6": (27, 39),
        "E7": (19, 40),
        "E8": (19, 40),
        "E9": (18, 40),
        "E10": (17, 41),
        "E11": (17, 41),
        "E12": (22, 41),
        "E13": (21, 41),
        "E14": (29, 41),
        "E15": (30, 41),
        "E16": (31, 41),
    }
    # 决策变量
    x_firstE = LpVariable.dicts(
        "x_firstE",
        ((i, j, t) for i in landsE for j in first_season_cropsE for t in years),
        lowBound=0,  # 最小种植面积
        cat="Continuous",
    )
    x_secondE = LpVariable.dicts(
        "x_secondE",
        ((i, j, t) for i in landsE for j in second_season_cropsE for t in years),
        lowBound=0,  # 最小种植面积
        cat="Continuous",
    )
    z_firstE = LpVariable.dicts(
        "z_firstE",
        ((i, j, t) for i in landsE for j in first_season_cropsE for t in years),
        cat="Binary",
    )
    z_secondE = LpVariable.dicts(
        "z_secondE",
        ((i, j, t) for i in landsE for j in second_season_cropsE for t in years),
        cat="Binary",
    )

    overproduction_secondE = LpVariable.dicts(
        "overproduction_secondE",
        ((j, t) for j in second_season_cropsE for t in years),
        lowBound=0,
        cat="Continuous",
    )

    # 约束条件1：每块地每连续三年必须种植豆类（第一季的17, 18, 19）
    for i in landsE:
        # 考虑2023, 2024, 2025三个连续年份
        model += (
            lpSum(
                (
                    x_firstE[i, j, 2024]
                    + x_firstE[i, j, 2025]
                    + (
                        area_of_landE[i]
                        if known_planting_2023E[i][0] in [17, 18, 19]
                        else 0
                    )
                )
                for j in [17, 18, 19]
            )
            >= area_of_landE[i]
        )

        # 从2024年开始，每三个连续年份至少有一个豆类作物
        for t in range(2024, 2029):
            model += (
                lpSum(x_firstE[i, j, t + k] for j in [17, 18, 19] for k in range(3))
                >= area_of_landE[i]
            )

    # 约束条件2：同一块地在连续两年内不能种植相同的作物
    M = 1000
    for i in landsE:
        # 第一季作物的重茬约束
        for j in first_season_cropsE:
            for t in range(2024, 2030):
                model += x_firstE[i, j, t] <= M * z_firstE[i, j, t]
                model += z_firstE[i, j, t] + z_firstE[i, j, t + 1] <= 1

        # 第二季作物的重茬约束
        for j in second_season_cropsE:
            for t in range(2024, 2030):
                model += x_secondE[i, j, t] <= M * z_secondE[i, j, t]
                model += z_secondE[i, j, t] + z_secondE[i, j, t + 1] <= 1

    # 2024年不能与2023年种植的作物重茬
    for i, (first_crop, second_crop) in known_planting_2023E.items():
        # 第一季作物不能重茬种植
        if first_crop in first_season_cropsE:
            model += z_firstE[i, first_crop, 2024] == 0
        # 第二季作物不能重茬种植
        if second_crop in second_season_cropsE:
            model += z_secondE[i, second_crop, 2024] == 0

    # 约束条件3：第一季和第二季的种植面积总和不能超过地块面积
    for i in landsE:
        for t in years:
            # 第一季作物的种植总面积不超过地块面积
            model += (
                lpSum(x_firstE[i, j, t] for j in first_season_cropsE)
                <= area_of_landE[i]
            )
            # 第二季作物的种植总面积不超过地块面积
            model += (
                lpSum(x_secondE[i, j, t] for j in second_season_cropsE)
                <= area_of_landE[i]
            )

    # 第二季作物的总产量限制
    for j in second_season_cropsE:
        for t in years:
            total_yield_secondE = lpSum(
                mapping.get_yield_idtype(j, field_typeE, "第二季")
                * samples_list[t]["亩产量"]
                * x_secondE[i, j, t]
                for i in landsE
            )
            model += (
                total_yield_secondE
                <= total_salesE[j] * samples_list[t]["其他销量"]
                + overproduction_secondE[j, t]
            )
            model += (
                overproduction_secondE[j, t]
                >= total_yield_secondE - total_salesE[j] * samples_list[t]["其他销量"]
            )

    # endregion

    # region F
    # 地块、作物、时间范围
    landsF = ["F1", "F2", "F3", "F4"]
    first_season_cropsF = list(range(17, 35))  # 第一季作物编号
    second_season_cropsF = [21, 22, 23, 24, 28, 29, 30, 34]  # 第二季作物编号
    field_typeF = "智慧大棚"
    years = range(2024, 2031)
    # 面积数据
    area_of_landF = {land: 0.6 for land in landsF}

    total_salesF = {
        21: 810.0,
        22: 2160.0,
        23: 900.0,
        24: 810.0,
        28: 1080.0,
        29: 4050.0,
        30: 1350.0,
        34: 1800.0,
    }

    # 2023年的种植方案
    known_planting_2023F = {
        "F1": ((32, 0.3), (33, 0.3), (24, 0.3), (21, 0.3)),
        "F2": ((25, 0.3), (26, 0.3), (22, 0.3), (29, 0.3)),
        "F3": ((17, 0.6), (28, 0.3), (30, 0.3)),
        "F4": ((19, 0.6), (34, 0.3), (23, 0.3)),
    }

    # 决策变量
    x_firstF = LpVariable.dicts(
        "x_firstF",
        ((i, j, t) for i in landsF for j in first_season_cropsF for t in years),
        lowBound=0,
        cat="Continuous",
    )
    x_secondF = LpVariable.dicts(
        "x_secondF",
        ((i, j, t) for i in landsF for j in second_season_cropsF for t in years),
        lowBound=0,
        cat="Continuous",
    )
    z_firstF = LpVariable.dicts(
        "z_firstF",
        ((i, j, t) for i in landsF for j in first_season_cropsF for t in years),
        cat="Binary",
    )
    z_secondF = LpVariable.dicts(
        "z_secondF",
        ((i, j, t) for i in landsF for j in second_season_cropsF for t in years),
        cat="Binary",
    )

    overproduction_secondF = LpVariable.dicts(
        "overproduction_secondF",
        ((j, t) for j in second_season_cropsF for t in years),
        lowBound=0,
        cat="Continuous",
    )

    # 约束条件1：每块地每连续三年必须种植豆类（第一季的17, 19）
    for i in landsF:
        # 考虑2023, 2024, 2025三个连续年份
        model += (
            lpSum(
                (
                    x_firstF[i, j, 2024]
                    + x_firstF[i, j, 2025]
                    + (
                        area_of_landF[i]
                        if known_planting_2023F[i][0][0] in [17, 19]
                        else 0
                    )
                )
                for j in [17, 19]
            )
            >= area_of_landF[i]
        )

        # 从2024年开始，每三个连续年份至少有一个豆类作物
        for t in range(2024, 2029):
            model += (
                lpSum(x_firstF[i, j, t + k] for j in [17, 19] for k in range(3))
                >= area_of_landF[i]
            )

    # 约束条件2：同一块地在连续两年内不能种植相同的作物
    M = 1000
    for i in landsF:
        # 第一季作物的重茬约束
        for j in first_season_cropsF:
            for t in range(2024, 2030):
                model += x_firstF[i, j, t] <= M * z_firstF[i, j, t]
                model += z_firstF[i, j, t] + z_firstF[i, j, t + 1] <= 1

        # 第二季作物的重茬约束
        for j in second_season_cropsF:
            for t in range(2024, 2030):
                model += x_secondF[i, j, t] <= M * z_secondF[i, j, t]
                model += z_secondF[i, j, t] + z_secondF[i, j, t + 1] <= 1

    # 新的重茬约束：每年第一季度不能和第二季度的同一块地种植相同的作物
    for i in landsF:
        for j in first_season_cropsF:
            if j in second_season_cropsF:
                for t in years:
                    model += x_firstF[i, j, t] + x_secondF[i, j, t] <= M * (
                        z_firstF[i, j, t] + z_secondF[i, j, t]
                    )

    # 新的重茬约束：每年第二季度不能和下一年第一季度种植相同的作物
    for i in landsF:
        for j in second_season_cropsF:
            if j in first_season_cropsF:
                for t in range(2024, 2030):
                    model += x_secondF[i, j, t] + x_firstF[i, j, t + 1] <= M * (
                        z_secondF[i, j, t] + z_firstF[i, j, t + 1]
                    )

    # 2024年不能与2023年种植的作物重茬
    for i, crops in known_planting_2023F.items():
        for first_crop, second_crop in crops:
            if first_crop in first_season_cropsF:
                model += z_firstF[i, first_crop, 2024] == 0
            if second_crop in second_season_cropsF:
                model += z_secondF[i, second_crop, 2024] == 0
            if first_crop in second_season_cropsF:
                model += z_firstF[i, first_crop, 2024] == 0

    # 约束条件3：第一季和第二季的种植面积总和不能超过地块面积
    for i in landsF:
        for t in years:
            model += (
                lpSum(x_firstF[i, j, t] for j in first_season_cropsF)
                <= area_of_landF[i]
            )
            model += (
                lpSum(x_secondF[i, j, t] for j in second_season_cropsF)
                <= area_of_landF[i]
            )

    # # 约束条件4：作物总产量限制

    for j in second_season_cropsF:
        for t in years:
            total_yield_secondF = lpSum(
                mapping.get_yield_idtype(j, field_typeF, "第二季")
                * samples_list[t]["亩产量"]
                * x_secondF[i, j, t]
                for i in landsF
            )
            model += (
                total_yield_secondF
                <= total_salesF[j] * samples_list[t]["其他销量"]
                + overproduction_secondF[j, t]
            )
            model += (
                overproduction_secondF[j, t]
                >= total_yield_secondF - total_salesF[j] * samples_list[t]["其他销量"]
            )

    # endregion

    # region first_season
    # 每种作物的总销量（/斤）
    total_sales_first = {
        17: 36480.0,
        18: 26880.0,
        19: 6480.0,
        20: 30000.0,
        21: 35400.0,
        22: 43200.0,
        23: 0.0,
        24: 1800.0,
        25: 3600.0,
        26: 4050.0,
        27: 4500.0,
        28: 34400.0,
        29: 9000.0,
        30: 1500.0,
        31: 1200.0,
        32: 3600.0,
        33: 1800.0,
        34: 0.0,
    }

    first_season_crop = list(range(17, 35))

    # 定义全局超出变量
    overproduction_first = LpVariable.dicts(
        "overproduction_first",
        ((j, t) for j in first_season_crop for t in years),
        lowBound=0,
        cat="Continuous",
    )
    # 全局超出变量的下限
    for j in first_season_crop:
        for t in years:
            total_yield_first_all = (
                lpSum(
                    mapping.get_yield_idtype(j, field_typeD, "第一季")
                    * samples_list[t]["亩产量"]
                    * x_firstD[i, j, t]
                    for i in landsD
                )
                + lpSum(
                    mapping.get_yield_idtype(j, field_typeE, "第一季")
                    * samples_list[t]["亩产量"]
                    * x_firstE[i, j, t]
                    for i in landsE
                )
                + lpSum(
                    mapping.get_yield_idtype(j, field_typeF, "第一季")
                    * samples_list[t]["亩产量"]
                    * x_firstF[i, j, t]
                    for i in landsF
                )
            )
            model += (
                total_yield_first_all
                <= total_sales_first[j] * samples_list[t]["其他销量"]
                + overproduction_first[j, t]
            )
            model += (
                overproduction_first[j, t]
                >= total_yield_first_all
                - total_sales_first[j] * samples_list[t]["其他销量"]
            )

    # 目标函数：最大化总利润，并惩罚超出部分
    model += (
        lpSum(
            mapping.get_profit_idtype(j, field_typeD, "单季")
            * x_singleD[i, j, t]
            * mapping.get_yield_idtype(j, field_typeD, "单季")
            * samples_list[t]["亩产量"]
            for i in landsD
            for j in single_season_cropsD
            for t in years
        )
        + lpSum(
            mapping.get_profit_idtype(j, field_typeD, "第一季")
            * x_firstD[i, j, t]
            * mapping.get_yield_idtype(j, field_typeD, "第一季")
            * samples_list[t]["亩产量"]
            for i in landsD
            for j in first_season_cropsD
            for t in years
        )
        + lpSum(
            mapping.get_profit_idtype(j, field_typeD, "第二季")
            * x_secondD[i, j, t]
            * mapping.get_yield_idtype(j, field_typeD, "第二季")
            * samples_list[t]["亩产量"]
            for i in landsD
            for j in second_season_cropsD
            for t in years
        )
        - lpSum(
            overproduction_singleD[j, t] * mapping.get_priceperjin_idtypeD(j)
            for j in single_season_cropsD
            for t in years
        )
        - lpSum(
            overproduction_secondD[j, t] * mapping.get_priceperjin_idtypeD(j)
            for j in second_season_cropsD
            for t in years
        )
        + lpSum(
            mapping.get_profit_idtype(j, field_typeE, "第一季")
            * x_firstE[i, j, t]
            * mapping.get_yield_idtype(j, field_typeE, "第一季")
            * samples_list[t]["亩产量"]
            for i in landsE
            for j in first_season_cropsE
            for t in years
        )
        + lpSum(
            mapping.get_profit_idtype(j, field_typeE, "第二季")
            * x_secondE[i, j, t]
            * mapping.get_yield_idtype(j, field_typeE, "第二季")
            * samples_list[t]["亩产量"]
            for i in landsE
            for j in second_season_cropsE
            for t in years
        )
        - lpSum(
            overproduction_secondE[j, t] * mapping.get_priceperjin_idtypeE(j)
            for j in second_season_cropsE
            for t in years
        )
        + lpSum(
            mapping.get_profit_idtype(j, field_typeF, "第一季")
            * x_firstF[i, j, t]
            * mapping.get_yield_idtype(j, field_typeF, "第一季")
            * samples_list[t]["亩产量"]
            for i in landsF
            for j in first_season_cropsF
            for t in years
        )
        + lpSum(
            mapping.get_profit_idtype(j, field_typeF, "第二季")
            * x_secondF[i, j, t]
            * mapping.get_yield_idtype(j, field_typeF, "第二季")
            * samples_list[t]["亩产量"]
            for i in landsF
            for j in second_season_cropsF
            for t in years
        )
        - lpSum(
            overproduction_secondF[j, t] * mapping.get_priceperjin_idtypeF(j)
            for j in second_season_cropsF
            for t in years
        )
        - lpSum(
            overproduction_first[j, t] * mapping.get_priceperjin_idtypeD(j)
            for j in first_season_crop
            for t in years
        )
    )

    # 启用CBC求解器的详细输出
    # solver = PULP_CBC_CMD(msg=False, gapRel=0.05, timeLimit=10)
    solver = PULP_CBC_CMD(msg=False, gapRel=0.05, timeLimit=10)

    # 求解模型
    model.solve(solver)
    # endregion

    return (
        x_singleD,
        x_firstD,
        x_secondD,
        x_firstE,
        x_secondE,
        x_firstF,
        x_secondF,
        total_salesD,
        total_salesE,
        total_salesF,
        total_sales_first,
        years,
        landsD,
        landsE,
        landsF,
        single_season_cropsD,
        first_season_cropsD,
        second_season_cropsD,
        first_season_cropsE,
        second_season_cropsE,
        first_season_cropsF,
        second_season_cropsF,
        first_season_crop,
        field_typeD,
        field_typeE,
        field_typeF,
    )


def calculate_total_profit(
    samples_list,
    x_singleD,
    x_firstD,
    x_secondD,
    x_firstE,
    x_secondE,
    x_firstF,
    x_secondF,
    total_salesD,
    total_salesE,
    total_salesF,
    total_sales_first,
    years,
    landsD,
    landsE,
    landsF,
    single_season_cropsD,
    first_season_cropsD,
    second_season_cropsD,
    first_season_cropsE,
    second_season_cropsE,
    first_season_cropsF,
    second_season_cropsF,
    first_season_crop,
    field_typeD,
    field_typeE,
    field_typeF,
):
    # 初始化一个字典来存储每年的总利润
    annual_profit = {t: 0 for t in years}

    # 初始化字典来存储各个超出变量的值
    overproduction_singleD = {}
    overproduction_secondD = {}
    overproduction_secondE = {}
    overproduction_secondF = {}
    overproduction_first = {}

    # 逐年逐作物计算超出部分
    for t in years:
        # 计算单季作物的超出部分
        for j in single_season_cropsD:
            total_yield_singleD = sum(
                mapping.get_yield_idtype(j, field_typeD, "单季")
                * samples_list[t]["亩产量"]
                * x_singleD[i, j, t].value()
                for i in landsD
            )
            max_sales = total_salesD[j] * samples_list[t]["其他销量"]
            overproduction_singleD[(j, t)] = max(0, total_yield_singleD - max_sales)

        # 计算第二季作物的超出部分
        for j in second_season_cropsD:
            total_yield_secondD = sum(
                mapping.get_yield_idtype(j, field_typeD, "第二季")
                * samples_list[t]["亩产量"]
                * x_secondD[i, j, t].value()
                for i in landsD
            )
            max_sales = total_salesD[j] * samples_list[t]["其他销量"]
            overproduction_secondD[(j, t)] = max(0, total_yield_secondD - max_sales)

        for j in second_season_cropsE:
            total_yield_secondE = sum(
                mapping.get_yield_idtype(j, field_typeE, "第二季")
                * samples_list[t]["亩产量"]
                * x_secondE[i, j, t].value()
                for i in landsE
            )
            max_sales = total_salesE[j] * samples_list[t]["其他销量"]
            overproduction_secondE[(j, t)] = max(0, total_yield_secondE - max_sales)

        for j in second_season_cropsF:
            total_yield_secondF = sum(
                mapping.get_yield_idtype(j, field_typeF, "第二季")
                * samples_list[t]["亩产量"]
                * x_secondF[i, j, t].value()
                for i in landsF
            )
            max_sales = total_salesF[j] * samples_list[t]["其他销量"]
            overproduction_secondF[(j, t)] = max(0, total_yield_secondF - max_sales)

        # 计算第一季作物的超出部分
        for j in first_season_crop:
            total_yield_first_all = (
                sum(
                    mapping.get_yield_idtype(j, field_typeD, "第一季")
                    * samples_list[t]["亩产量"]
                    * x_firstD[i, j, t].value()
                    for i in landsD
                )
                + sum(
                    mapping.get_yield_idtype(j, field_typeE, "第一季")
                    * samples_list[t]["亩产量"]
                    * x_firstE[i, j, t].value()
                    for i in landsE
                )
                + sum(
                    mapping.get_yield_idtype(j, field_typeF, "第一季")
                    * samples_list[t]["亩产量"]
                    * x_firstF[i, j, t].value()
                    for i in landsF
                )
            )
            max_sales = total_sales_first[j] * samples_list[t]["其他销量"]
            overproduction_first[(j, t)] = max(0, total_yield_first_all - max_sales)

    # 计算每年的总收益和惩罚项
    for t in years:
        # 计算当年的总收益
        total_revenue = (
            sum(
                mapping.get_profit_idtype(j, field_typeD, "单季")
                * x_singleD[i, j, t].value()
                * mapping.get_yield_idtype(j, field_typeD, "单季")
                * samples_list[t]["亩产量"]
                for i in landsD
                for j in single_season_cropsD
            )
            + sum(
                (
                    mapping.get_profit_idtype(j, field_typeD, "第一季")
                    + mapping.get_price_idtype(j, field_typeD, "第一季")
                    * (samples_list[t]["蔬菜价格"] - 1)
                )
                * x_firstD[i, j, t].value()
                * mapping.get_yield_idtype(j, field_typeD, "第一季")
                * samples_list[t]["亩产量"]
                for i in landsD
                for j in first_season_cropsD
            )
            + sum(
                (
                    mapping.get_profit_idtype(j, field_typeD, "第二季")
                    + (
                        mapping.get_price_idtype(j, field_typeD, "第二季")
                        * (
                            (samples_list[t]["食用菌价格"] if j in [38, 39, 40] else 1)
                            - 1
                        )
                        * ((samples_list[t]["羊肚菌价格"] if j == 41 else 1) - 1)
                    )
                )
                * x_secondD[i, j, t].value()
                * mapping.get_yield_idtype(j, field_typeD, "第二季")
                * samples_list[t]["亩产量"]
                for i in landsD
                for j in second_season_cropsD
            )
            + sum(
                (
                    mapping.get_profit_idtype(j, field_typeE, "第一季")
                    + mapping.get_price_idtype(j, field_typeE, "第一季")
                    * (samples_list[t]["蔬菜价格"] - 1)
                )
                * x_firstE[i, j, t].value()
                * mapping.get_yield_idtype(j, field_typeE, "第一季")
                * samples_list[t]["亩产量"]
                for i in landsE
                for j in first_season_cropsE
            )
            + sum(
                mapping.get_profit_idtype(j, field_typeE, "第二季")
                * x_secondE[i, j, t].value()
                * mapping.get_yield_idtype(j, field_typeE, "第二季")
                * samples_list[t]["亩产量"]
                for i in landsE
                for j in second_season_cropsE
            )
            + sum(
                (
                    mapping.get_profit_idtype(j, field_typeF, "第一季")
                    + mapping.get_price_idtype(j, field_typeF, "第一季")
                    * (samples_list[t]["蔬菜价格"] - 1)
                )
                * x_firstF[i, j, t].value()
                * mapping.get_yield_idtype(j, field_typeF, "第一季")
                * samples_list[t]["亩产量"]
                for i in landsF
                for j in first_season_cropsF
            )
            + sum(
                (
                    mapping.get_profit_idtype(j, field_typeF, "第二季")
                    + mapping.get_price_idtype(j, field_typeF, "第二季")
                    * (samples_list[t]["蔬菜价格"] - 1)
                )
                * x_secondF[i, j, t].value()
                * mapping.get_yield_idtype(j, field_typeF, "第二季")
                * samples_list[t]["亩产量"]
                for i in landsF
                for j in second_season_cropsF
            )
        )

        # 计算当年的惩罚项（超出部分）
        total_penalty = (
            sum(
                overproduction_singleD[(j, t)] * mapping.get_priceperjin_idtypeD(j)
                for j in single_season_cropsD
            )
            + sum(
                overproduction_secondD[(j, t)]
                * mapping.get_priceperjin_idtypeD(j)
                * (samples_list[t]["食用菌价格"] if j in [38, 39, 40] else 1)
                * (samples_list[t]["羊肚菌价格"] if j == 41 else 1)
                for j in second_season_cropsD
            )
            + sum(
                overproduction_secondE[(j, t)] * mapping.get_priceperjin_idtypeE(j)
                for j in second_season_cropsE
            )
            + sum(
                overproduction_secondF[(j, t)]
                * mapping.get_priceperjin_idtypeF(j)
                * (samples_list[t]["蔬菜价格"] - 1)
                for j in second_season_cropsF
            )
            + sum(
                overproduction_first[(j, t)]
                * mapping.get_priceperjin_idtypeD(j)
                * (samples_list[t]["蔬菜价格"] - 1)
                for j in first_season_crop
            )
        )

        annual_profit[t] = total_revenue - total_penalty

    total_profit = sum(annual_profit[t] for t in years)

    return total_profit
